package cn.hfjava.kz.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import cn.hfjava.kz.config.OssConfig;
import cn.hfjava.kz.config.properties.KzUploadProperties;
import cn.hfjava.kz.config.properties.MdUploadProperties;
import cn.hfjava.kz.entity.po.Document;
import cn.hfjava.kz.entity.po.Student;
import cn.hfjava.kz.entity.po.Templates;
import cn.hfjava.kz.exception.BizException;
import cn.hfjava.kz.mapper.DocumentMapper;
import cn.hfjava.kz.mapper.UserMapper;
import cn.hfjava.kz.service.StudentService;
import cn.hfjava.kz.service.TemplatesService;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.io.file.FileNameUtil;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectResult;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.MultipartConfigElement;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 公共上传前端控制器
 *
 * @author lds
 * @date 2024/07/15 10:23
 */
@RestController
@RequestMapping("/api/v1/upload")
@Tag(name = "文件上传接口")
@Slf4j
public class UploadController {

    /*
        #上传文件时，默认单个上传文件大小是1MB，max-file-size设置单个上传文件大小
        spring.servlet.multipart.max-file-size=50MB
        #默认总文件大小是10MB，max-request-size设置总上传文件大小
        spring.servlet.multipart.max-request-size=500MB
        byte[]getBytes() 获取文件数据
        String getContentType() 获取文件MIME类型
        InputStream getInputStream() 获取表单中文件组件的名字
        String getName() 获取表单中文件组件的名字
        String getOriginalFilename() 获取上传文件的原名
        long getSize() 获取文件的字节大小
        boolean isEmpty() 是否有选择上传文件
        void transferTo() 将上传文件保存到一个目标文件中


         // 设置上传后的文件名称（拼接）
        String newFileName = username + UUID.randomUUID() + "_" + originalFilename;
     */
    @Resource
    private KzUploadProperties kzUploadProperties;
    @Resource
    private OSS ossClient;
    @Resource
    private UserMapper userMapper;
    @Resource
    private StudentService studentService;

    @Resource
    private MultipartConfigElement multipartConfigElement;

    @Resource
    private DocumentMapper documentMapper;
    @Resource
    private OssConfig ossConfig;
    @Resource
    private TemplatesService templatesService;
    @Resource
    private MdUploadProperties mdUploadProperties;

    private static final List<String> IMAGE_TYPE = Arrays.asList("png", "jpg", "jpeg");
    private static final List<String> FILE_TYPE = Arrays.asList("pdf");
    private static final List<String> TEMPLATE_FILE_TYPE = Arrays.asList("xlsx", "docx");
    private static final List<String> MODE_TYPE = Arrays.asList("doc", "docx","xlsx");

    @Operation(summary = "上传图片文件")
    @PostMapping(value = "/image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public SaResult uploadImage(
            @RequestPart(name = "file", required = true) MultipartFile file,
//            @RequestParam(value = "studentId") Integer studentId,
            @RequestParam(value = "imageType", required = false) String imageType) {
        String bucketName = ossConfig.getBucketName();
        String endPoint = ossConfig.getEndPoint();
        String accessKeyId = ossConfig.getAccessKeyId();
        String accessKeySecret = ossConfig.getAccessKeySecret();
        // png、jpg、jpeg   10MB
        if (file == null || file.getSize() == 0) {
            return SaResult.error("上传图片不能为空");
        }
        String fileName = file.getOriginalFilename();
        String fileSuffix = fileName.substring(fileName.lastIndexOf(".")); // .jpg
        String fileExt = FileNameUtil.extName(fileName); // jpg
        Long fileSize = file.getSize();
        if (!IMAGE_TYPE.contains(fileExt)) {
            return SaResult.error("上传图片格式错误，仅支持(.jpg,.jpeg,.png)格式");
        }
        if (fileSize > multipartConfigElement.getMaxFileSize()) {
            return SaResult.error("上传图片大小不能超过10MB");
        }

//        Student student = studentService.getById(studentId);
//        if (student == null) {
//            return SaResult.error("此考生不存在");
//        }

        /*
         *  手机号_身份证正面.jpg
         *  手机号_身份证反面.jpg
         *  手机号_毕业证书.jpg
         *  手机号_个人相片.jpg
         *  手机号_职工个人参保证明.pdf
         */
        switch (imageType) {
            case "idCardFront":
                fileName = "_身份证(正面)" + fileSuffix;
                break;
            case "idCardBack":
                fileName =   "_身份证(反面)" + fileSuffix;
                break;
            case "CertNo":
                fileName =  "_毕业证书" + fileSuffix;
                break;
            case "Photo":
                fileName =  "_个人相片" + fileSuffix;
                break;
            default:
                return SaResult.error("上传图片类型错误");
        }


//        String uploadPath = kzUploadProperties.getUploadPath();
//      /*  LocalDateTime now = LocalDateTime.now();
//        String yearPath = String.valueOf(now.getYear());
//        String monthPath = String.valueOf(now.getMonthValue());
//        String dayPath = String.valueOf(now.getDayOfMonth());*/
//        //String dirPath = yearPath + "/" + monthPath + "/" + dayPath + "/" + userEntity.getUsername() + "/";
//
//        String dirPath = student.getName().concat("_").concat(student.getPhone());  // D:/kz/uploadPath/20240816/张三//**/
//
//        File dirFile = new File(uploadPath, dirPath);
//        if (!dirFile.exists()) {
//            dirFile.mkdirs();
//        }
//        File destFile = new File(dirFile, fileName);
        //创建OSS对象
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);

        //获取原生文件名
//        String originalFilename = file.getOriginalFilename();
        //JDK8的日期格式
//        LocalDateTime time = LocalDateTime.now();
//        DateTimeFormatter dft = DateTimeFormatter.ofPattern("yyyy/MM/dd");

//        拼装OSS上存储的路径
//        String folder = dft.format(time);
//        String Name = generateUUID();
//        String extension = fileName.substring(fileName.lastIndexOf("."));
        String uploadFileName = imageType + "/" + fileName;

        try {
            PutObjectResult result = ossClient.putObject(bucketName, uploadFileName, file.getInputStream());
            //拼装返回路径
            if (result != null) {
                String createdUser = String.valueOf(StpUtil.getExtra("username"));
                Integer userId = StpUtil.getLoginIdAsInt();
                fileName = fileName.substring(0, fileName.lastIndexOf("."));
//                String imageUrl = "https://"+bucketName+"."+endPoint+"/"+uploadFileName;
                HashMap<String, String> objectObjectHashMap = new HashMap<>();
                Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
                URL imageUrl = ossClient.generatePresignedUrl(bucketName, uploadFileName, expiration);
                objectObjectHashMap.put("url", imageUrl.toString());
                objectObjectHashMap.put("path", uploadFileName);
//                if (!(documentMapper.selectCount(new QueryWrapper<Document>().eq("title", fileName)) > 0)) {
//                    documentMapper.saveDoc(fileName, fileExt, imageUrl.toString(), uploadFileName, createdUser, userId, studentId);
//                } else {
//                    return SaResult.error("不能重复上传！");
//                }
                return SaResult.ok().setData(objectObjectHashMap);
            }
        } catch (IOException e) {
            log.error("文件上传失败:{}",e.getMessage());
        } finally {
            //OSS关闭服务，不然会造成OOM
            ossClient.shutdown();
        }
        return SaResult.error("图片上传失败");
//        try {
//            file.transferTo(destFile);
//            String imagePath = kzUploadProperties.getAssetsUrl()
//                    .replaceFirst("\\*\\*", "") + dirPath + fileName;
//            String imageUrl = kzUploadProperties.getBaseUrl() + imagePath;
//            Map<String, String> imageMap = new HashMap<>();
//            imageMap.put("url", imageUrl);
//            imageMap.put("path", imagePath);

        //获取上传人的userId、studentId和用户名

//        } catch (IOException ex) {
//            throw new BizException(500, "上传图片失败", ex);
//        }
    }


    @Operation(summary = "上传PDF文件")
    @PostMapping(value = "/pdfFile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public SaResult uploadPdfFile(
            @RequestPart(name = "file", required = true) MultipartFile file
            ) {
        String bucketName = ossConfig.getBucketName();
        String endPoint = ossConfig.getEndPoint();
        String accessKeyId = ossConfig.getAccessKeyId();
        String accessKeySecret = ossConfig.getAccessKeySecret();
        // pdf、doc、docx  10MB
        if (file == null || file.getSize() == 0) {
            return SaResult.error("上传文件不能为空");
        }
        String fileName = file.getOriginalFilename();
        String fileExt = FileNameUtil.extName(fileName); // jpg，不是.jpg
        Long fileSize = file.getSize();
        if (!FILE_TYPE.contains(fileExt)) {
            return SaResult.error("上传文件格式错误，仅支持(.pdf)格式");
        }
        if (fileSize > multipartConfigElement.getMaxFileSize()) {
            return SaResult.error("上传文件大小不能超过10MB");
        }


//        Student student = studentService.getById(studentId);
//        if (student == null) {
//            return SaResult.error("此考生不存在");
//        }
        fileName = "_职工个人参保证明.pdf";

//        String dirPath = student.getName().concat("_").concat(student.getPhone()) + "/"; //   D:/kz/uploadPath/20240816/张三/
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
        String uploadFileName = "didi"  + fileName;
        try {
            PutObjectResult result = ossClient.putObject(bucketName, uploadFileName, file.getInputStream());
            //拼装返回路径
            if (result != null) {
                String createdUser = String.valueOf(StpUtil.getExtra("username"));
                Integer userId = StpUtil.getLoginIdAsInt();
                fileName = fileName.substring(0, fileName.lastIndexOf("."));
//                String pdfUrl = "https://"+bucketName+"."+endPoint+"/"+uploadFileName;
                HashMap<String, String> objectObjectHashMap = new HashMap<>();
                Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
                URL pdfurl = ossClient.generatePresignedUrl(bucketName, uploadFileName, expiration);
                objectObjectHashMap.put("url", pdfurl.toString());
                objectObjectHashMap.put("path", uploadFileName);
//                if (!(documentMapper.selectCount(new QueryWrapper<Document>().eq("title", fileName)) > 0)) {
//                    documentMapper.saveDoc(fileName, fileExt, pdfurl.toString(), uploadFileName, createdUser, userId, studentId);
//                } else {
//                    return SaResult.error("不能重复上传！");
//                }
                return SaResult.ok().setData(objectObjectHashMap);
            }
        } catch (IOException e) {
            log.error("文件上传失败:{}",e.getMessage());
        } finally {
            //OSS关闭服务，不然会造成OOM
            ossClient.shutdown();
        }
        return SaResult.error("文件上传失败");
    }


    @Operation(summary = "上传模板")
    @PostMapping(value = "/uploadMode", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public SaResult uploadModel(
            @RequestPart(name = "file", required = true) MultipartFile file) {
        String bucketName = ossConfig.getBucketName();
        String endPoint = ossConfig.getEndPoint();
        String accessKeyId = ossConfig.getAccessKeyId();
        String accessKeySecret = ossConfig.getAccessKeySecret();
        // pdf、doc、docx  10MB
        if (file == null || file.getSize() == 0) {
            return SaResult.error("上传模板不能为空");
        }
        String fileName = "";
        fileName = file.getOriginalFilename();
        String[] split = fileName.split("\\.");
        String name = split[0];
        //String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1); // jpg
        String fileExt = FileNameUtil.extName(fileName); // jpg，不是.jpg
        Long fileSize = file.getSize();
        if (!MODE_TYPE.contains(fileExt)) {
            return SaResult.error("上传模板格式错误，仅支持(.doc,.dox,.xlsx)格式");
        }
        if (fileSize > multipartConfigElement.getMaxFileSize()) {
            return SaResult.error("上传模板大小不能超过10MB");
        }

        Integer loginId = StpUtil.getLoginIdAsInt();
//        User userEntity = userService.getById(loginId);
        String dirPath = "Templates/";
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
        String uploadFileName = dirPath  + fileName;

        Templates templates = new Templates();
        templates.setTemtype(fileExt);
        templates.setTemname(name);

        templates.setCreateddate(DateTime.now());
        templates.setUpdateddate(DateTime.now());
        templates.setTemaddress(uploadFileName);
        try {
            PutObjectResult result = ossClient.putObject(bucketName, uploadFileName, file.getInputStream());
            //拼装返回路径
            if (result != null) {
                System.out.println(result);
                String createdUser = String.valueOf(StpUtil.getExtra("username"));
                Integer userId = StpUtil.getLoginIdAsInt();
                fileName = fileName.substring(0, fileName.lastIndexOf("."));
//                String fileUrl = "https://"+bucketName+"."+endPoint+"/"+uploadFileName;
                HashMap<String, String> objectObjectHashMap = new HashMap<>();
                Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
                URL modeurl = ossClient.generatePresignedUrl(bucketName, uploadFileName, expiration);
                objectObjectHashMap.put("url", modeurl.toString());
                objectObjectHashMap.put("path", uploadFileName);
                templates.setTemUrl(modeurl.toString());
                templatesService.save(templates);
                return SaResult.ok().setData(objectObjectHashMap);
            }
        } catch (IOException e) {
            log.error("模板上传失败:{}",e.getMessage());
        } finally {
            //OSS关闭服务，不然会造成OOM
            ossClient.shutdown();
        }
        return SaResult.error("模板上传失败");

    }


    @Operation(summary = "下载文件")
    @GetMapping("/download")
    public void downloadFile(@RequestParam(value = "filePath") String filePath, HttpServletResponse response) throws IOException {
        OSSObject ossObject = ossClient.getObject(ossConfig.getBucketName(), filePath);
        InputStream downFile = ossObject.getObjectContent();

//
//        filePath = filePath.replace(kzUploadProperties.getBaseUrl() + kzUploadProperties.getAssetsUrl().replace("**", ""), "");
//        String basePath = kzUploadProperties.getUploadPath();
//        //basePath是基路径  filePath是指想要下载的文件的路径
//        File file = new File(basePath, filePath);
//        log.info("下载文件完整路径是：{},下载的文件是否存在：{}", file.getAbsolutePath(), file.exists());
//        if (file == null || !file.exists()) {
//            throw new BizException(500, "下载文件不存在");
//        }
        // 获取文件名
/*        String filename = file.getName();
        // 设置响应头*/
        // 指定下载文件名(attachment-以下载方式保存到本地，inline-在线预览)
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filePath, "UTF-8"));
        // 告知浏览器文件的大小
//        response.addHeader("Content-Length", "" + file.length());
        //设置响应的内容类型为二进制流，即文件类型
        response.setContentType("application/octet-stream");
        try (BufferedInputStream bis = new BufferedInputStream(downFile);
             BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream())) {
            byte[] buff = new byte[1024];
            int len;
            while ((len = bis.read(buff)) != -1) {
                bos.write(buff, 0, len);
            }
            bos.flush();
        } catch (IOException e) {
            throw new BizException(500, "下载文件失败");
        }
    }

    /*@PostMapping("/download")
    @Operation(summary = "下载文件")
    public void downloadFile(@RequestParam(value = "filename",required = true) String filename,
                         HttpServletResponse response) throws IOException {
        // 2024/07/16/李政浩/xxx.jpg
        // 2024/07/16/李政浩/xxx.docx
        if(! StringUtils.hasLength(filename)) {
            throw new BizException(400,"下载文件为空");
        }
        File file = new File(kzUploadProperties.getUploadPath(),filename);
        if(! file.exists()) {
            throw new BizException(400,"下载文件不存在");
        }
        // 设置响应报文
        response.setContentType("application/octet-stream");
        // 指定下载文件名(attachment-以下载方式保存到本地，inline-在线预览)
        response.addHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
        try(
                InputStream is = new FileInputStream(file);
                OutputStream os = response.getOutputStream()
        ){
            byte[] buffer = new byte[1024];
            int readBytes = 0;

            while((readBytes = is.read(buffer)) != -1) {
                os.write(buffer, 0, readBytes);
                os.flush();
            }
        }catch (IOException ex) {
            ex.printStackTrace();
            throw new RuntimeException("文件下载失败");
        }
    }*/


    @Operation(summary = "下载文件")
    @GetMapping("/downloadFile")
    public ResponseEntity<InputStreamResource> downloadFile(@RequestParam(value = "filePath") String filePath) throws IOException {
        filePath = filePath.replace(kzUploadProperties.getBaseUrl() + kzUploadProperties.getAssetsUrl().replace("**", ""), "");
        String basePath = kzUploadProperties.getUploadPath();
        // 从文件系统或其他来源获取文件
        File file = new File(basePath, filePath);
        // 创建文件输入流
        InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
        // 设置HTTP头信息
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", file.getName());

        // 返回ResponseEntity对象
        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(file.length())
                .body(resource);
    }
    @Operation(summary = "上传用户头像")
    @PostMapping(value = "/uploadAvater", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public SaResult uploadAvater(@RequestBody MultipartFile file,@RequestParam("id") Integer id) {
        String bucketName = ossConfig.getBucketName();
        String endPoint = ossConfig.getEndPoint();
        String accessKeyId = ossConfig.getAccessKeyId();
        String accessKeySecret = ossConfig.getAccessKeySecret();
        // png、jpg、jpeg   10MB
        if (file == null || file.getSize() == 0) {
            return SaResult.error("上传头像不能为空");
        }
        String fileName = file.getOriginalFilename();
        String fileSuffix = fileName.substring(fileName.lastIndexOf(".")); // .jpg
        String fileExt = FileNameUtil.extName(fileName); // jpg
        Long fileSize = file.getSize();
        if (!IMAGE_TYPE.contains(fileExt)) {
            return SaResult.error("上传头像格式错误，仅支持(.jpg,.jpeg,.png)格式");
        }
        if (fileSize > multipartConfigElement.getMaxFileSize()) {
            return SaResult.error("上传头像大小不能超过10MB");
        }
        //创建OSS对象
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
        String uploadFileName = fileName;

        try {
            PutObjectResult result = ossClient.putObject(bucketName, uploadFileName, file.getInputStream());
            //拼装返回路径
            if (result != null) {
                String createdUser = String.valueOf(StpUtil.getExtra("username"));
                Integer userId = StpUtil.getLoginIdAsInt();
                fileName = fileName.substring(0, fileName.lastIndexOf("."));
//                String imageUrl = "https://"+bucketName+"."+endPoint+"/"+uploadFileName;
                HashMap<String, String> objectObjectHashMap = new HashMap<>();
                Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
                URL imageUrl = ossClient.generatePresignedUrl(bucketName, uploadFileName, expiration);
                objectObjectHashMap.put("url", imageUrl.toString());
                objectObjectHashMap.put("path", uploadFileName);
                userMapper.updateAvater(id,imageUrl.toString());
//                if (!(userMapper.selectCount(new QueryWrapper<User>().eq("title", fileName)) > 0)) {
//                    documentMapper.saveDoc(fileName, fileExt, imageUrl.toString(), uploadFileName, createdUser, userId, 0);
//                }
//                } else {
//                    return SaResult.error("不能重复上传！");
//                }
                return SaResult.ok().setData(objectObjectHashMap);
            }
        } catch (IOException e) {
            return SaResult.error("头像上传失败");
        } finally {
            //OSS关闭服务，不然会造成OOM
            ossClient.shutdown();
        }
        return SaResult.error("头像上传失败");

    }
    /**
     * 获取随机字符串
     * @return
     */
    private String generateUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
    }
}

